﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using System.Linq;
using System.Management;

namespace ProcessLiveHelper
{
    class ProcessLiveInfo
    {
        public string Path { get; set; }
        public string WorkingDirectory { get; set; }
        public string Arguments { get; set; }
        public bool CreateNoWindow { get; set; } = true;
    }
    static class ProcessLiveService
    {
        static readonly object _logLock = new();
        static void Log(string msg)
        {
            lock (_logLock)
            {
                var now = DateTime.Now;
                var logFileName = $"log-{now.Year}-{now.Month}-{now.Day}.txt";
                File.AppendAllLines(logFileName, new[] { $"{now}:{msg}" });
            }
        }
        static void StartProcess(ProcessLiveInfo pl)
        {
            ProcessStartInfo startInfo = new();
            startInfo.FileName = pl.Path;
            startInfo.Arguments = pl.Arguments;
            startInfo.WorkingDirectory = pl.WorkingDirectory;
            startInfo.CreateNoWindow = pl.CreateNoWindow;
            Process.Start(startInfo);
        }
        static string GetArgsByPId(Process p)
        {
            var result = "";
            using (ManagementObjectSearcher mos = new(
                    $"SELECT CommandLine FROM Win32_Process WHERE ProcessId = {p.Id}"))
            {
                foreach (ManagementObject mo in mos.Get())
                {
                    result = mo["CommandLine"].ToString();
                    break;
                }
            }
            result = result.Trim();
            var index = result.IndexOf(" ");
            if (index == -1)
                return "";
            result =result.Remove(0, index);
            return result.Trim();
        }
        public static void Start(string plhJson)
        {
            try
            {
                List<ProcessLiveInfo> list = JsonSerializer.Deserialize<List<ProcessLiveInfo>>(File.ReadAllText(plhJson));
                List<Task> taskList = new();
                foreach(var plInfo in list)
                {
                    var task = new Task((info) => {
                        var pl = info as ProcessLiveInfo;
                        while (true)
                        {
                            try
                            {
                                var name = Path.GetFileNameWithoutExtension(pl.Path);
                                var ps=Process.GetProcessesByName(name);
                                if (ps.Length == 0)
                                {
                                    StartProcess(pl);
                                }
                                else if(!ps.Any(it => GetArgsByPId(it) == pl.Arguments.Trim()))
                                {
                                    StartProcess(pl);
                                }
                            }
                            catch (Exception ex)
                            {
                                Log(ex.GetBaseException().ToString());
                                throw new Exception(ex.Message,ex);
                            }
                            Thread.Sleep(3 * 1000);
                        }

                    },plInfo);
                    taskList.Add(task);
                    task.Start();
                }
                Task.WaitAll(taskList.ToArray());
            }
            catch(Exception ex)
            {
                Log(ex.ToString());
                throw new Exception(ex.Message, ex);
            }
        }
    }
}
